﻿#include "datawriter.h"

DataWriter::DataWriter(QSharedPointer<QByteArray> output)
{
    this->output = (output == nullptr)?QSharedPointer<QByteArray>(new QByteArray()):output;
    ds = QSharedPointer<QDataStream>(new QDataStream(this->output.data(),QIODevice::ReadWrite));
    ds->setByteOrder(QDataStream::ByteOrder::BigEndian);
    setToEnd();
    //we skip the data it have
    //then we write to it's end
}

DataWriter &DataWriter::writeShort(short data)
{
    setToEnd();
    *ds<<data;
    return *this;
}

DataWriter &DataWriter::writeUShort(ushort data)
{
    setToEnd();
    *ds<<data;
    return *this;
}

DataWriter &DataWriter::writeInt(int data)
{
    setToEnd();
    *ds<<data;
    return *this;
}

DataWriter &DataWriter::writeLong(quint64 data)
{
    setToEnd();
    *ds<<data;
    return *this;
}

DataWriter &DataWriter::writeByte(char data)
{
    setToEnd();
    ds->writeRawData(&data,1);
    return *this;
}

DataWriter &DataWriter::writeFloat(float data)
{
    setToEnd();
    *ds<<data;
    return *this;
}

DataWriter &DataWriter::writeDouble(double data)
{
    setToEnd();
    *ds<<data;
    return *this;
}

//well the code is so similar ,but i must use the implicit data type to confirm that i write the right data

DataWriter &DataWriter::writeBytes(QByteArray data, LengthType lengthType, int maxLength, uint lengthOffset)
{
    setToEnd();
    if(maxLength > -1)data = data.left(maxLength);//cut the data,or return full
    switch (lengthType) {
        case LengthType::SHORT:{writeShort(data.size()+lengthOffset);}break;
        case LengthType::INT:{writeInt(data.size()+lengthOffset);}break;
        case LengthType::BYTE:{writeByte(data.size()+lengthOffset);}break;
        default:abort();//WHAT YOU FUCK INPUT
    }
    writeRaw(data);
    return *this;
}

QSharedPointer<QByteArray> DataWriter::getData()
{
    return output;
}

DataWriter &DataWriter::writeRaw(const QByteArray &data)
{
    setToEnd();
    ds->writeRawData(data.data(),data.size());
    return *this;
}

DataWriter &DataWriter::writeRaw(DataWriter &dataWriter)
{
    return writeRaw(*dataWriter.getData());
}

DataWriter &DataWriter::writeProtobufBytes(const uint &id, const QByteArray &data)
{
    setToEnd();
    //hex(id<<3 | 2) length
    //so the length must short than one byte
    if(data.size() > 256)abort();
    writeByte((id<<3) | 2);
    writeByte(data.size());
    return writeRaw(data);
}

DataWriter &DataWriter::setToEnd()
{
    ds->device()->seek(output->size());
    return *this;
}

DataWriter &DataWriter::clear()
{
    output->clear();
    return *this;
}

int DataWriter::getSize()
{
    return output->size();
}

DataWriter::~DataWriter()
{
    //if(initBySelf)delete output;
    //delete ds;
}

void DataWriter::debug(int mode)
{
    if(mode == 0){
        QString tmp = output->toHex(' ');
        QStringList list = tmp.split(" ");
        for(int i = 0;i<list.size();++i){
            qDebug()<<i<<list[i];
        }
    }else{
        qDebug()<<output->toHex(' ');
    }
}
